#pragma once

#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <memory>
#include <functional>

#include "InetAddr.hpp"
#include "Log.hpp"
#include "Connection.hpp"

using namespace LogModule;

#define SIZE 1024 // 缓冲区大小

class Channel;
// using handler_t = std::function<void(std::shared_ptr<Channel>)>;

class Channel : public Connection
{
public:
    Channel(int sockfd, InetAddr &client) : _sockfd(sockfd),
                                            _client_addr(client)
    {
        SetNonBlock(sockfd); // 设置非阻塞模式
    }

    // 重写接收数据
    void Recver() override
    {
        // LOG(LogLevel::DEBUG) << "Channel::Recver";
        char buffer[SIZE];
        while (true)
        {
            buffer[0] = 0;                          // 清空buffer
            int n = recv(_sockfd, buffer, SIZE, 0); // 接收数据
            if (n > 0)
            {                        // 读取成功
                buffer[n] = 0;       // 结尾加上\0
                _inbuffer += buffer; // 追加到输入缓冲区
            }
            else if (n == 0)
            {               // 客户端意外关闭连接
                Excepter(); // 异常处理
                return;
            }
            else
            { // 读错误
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                {          // 数据读取完毕
                    break; // 跳出循环
                }
                else if (errno == EINTR)
                {             // 信号中断
                    continue; // 继续读
                }
                else
                {               // 其他错误
                    Excepter(); // 异常处理
                    return;
                }
            }
        }
        LOG(LogLevel::DEBUG) << "enter Channel::Recver, inbuffer: " << _inbuffer;

        if (!_inbuffer.empty())
            _outbuffer += _handler(_inbuffer); // channel调用回调处理

        if (!_outbuffer.empty())
            Sender(); // 发送数据
    }

    // 重写发送数据
    void Sender() override
    {
        while (1)
        {
            ssize_t n = send(_sockfd, _outbuffer.c_str(), _outbuffer.size(), 0); // 发送数据

            // 发送成功, 但不一定_outbuffer全部发完
            if (n > 0)
            {
                _outbuffer.erase(0, n); // 删除已发送的数据
                if (_outbuffer.empty())
                {
                    break; // 数据发送完毕, 跳出循环
                }
            }
            // 客户端意外关闭连接
            else if (n == 0)
            {
                break;
            }
            else
            { //发送失败, _outbuffer一个字节都没发出去
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                {          // 内核发送缓冲区满
                    break; // 跳出循环
                }
                else if (errno == EINTR)
                {             // 信号中断
                    continue; // 继续发送
                }
                else
                {               // 其他错误
                    Excepter(); // 异常处理
                    return;
                }
            }
        }

        // 1. _outbuffer为空, 发送完毕 
        // 2. 由于内核发送缓冲区满, _outbuffer只有部分发送成功
        if(!_outbuffer.empty())
        { // 原因2  
            GetOwner()->EnableReadWrite(_sockfd, true, true); // 使能读写事件
        }
        else
        { // 原因1
            GetOwner()->EnableReadWrite(_sockfd, true, false); // 使能读事件, 禁止写事件
        }
    }

    // 重写异常处理
    void Excepter() override
    {
        GetOwner()->DelConnection(_sockfd); // 从Reactor中删除该连接
    }

    int GetSockFd() override { return _sockfd; }                        // 获取sockfd
    std::string &InBuffer() { return _inbuffer; }                       // 获取_inbuffer
    void AppendOutBuffer(const std::string &out) { _outbuffer += out; } // 向_outbuffer末尾添加数据

    ~Channel()
    {
    }

private:
    int _sockfd; // socket 文件描述符

    std::string _inbuffer;  // 输入缓冲区
    std::string _outbuffer; // 输出缓冲区

    // 客户端地址信息
    InetAddr _client_addr;

    // handler_t _handler; // 事件处理器
};